package com.xbongbong.parent.abstracts;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasFormRichTextEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.FormDataHelp;
import com.xbongbong.paas.help.FormDataValidateDataHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.dto.FormDataUpdateDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.parent.help.CommonPermissionHelp;
import com.xbongbong.parent.interfaces.FormDataUpdateService;
import com.xbongbong.parent.interfaces.logger.OperationLogFactory;
import com.xbongbong.parent.interfaces.logger.OperationLogHandle;
import com.xbongbong.parent.pojo.UpdateValidateReturnPojo;
import com.xbongbong.pro.domain.entity.ReRollBackEntity;
import com.xbongbong.pro.enums.PaasStageEnum;
import com.xbongbong.pro.enums.RichTextEnum;
import com.xbongbong.pro.enums.errorcodes.QuotationErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.formdata.pojo.vo.BeforeUpdateVO;
import com.xbongbong.pro.formdata.pojo.vo.UpdateVO;
import com.xbongbong.pro.log.pojo.dto.UpdateOperationLogDTO;
import com.xbongbong.pro.permission.pojo.dto.VerifyUpdatePermissionDTO;
import com.xbongbong.pro.product.pojo.StockNotifyPojo;
import com.xbongbong.pro.service.toolbox.elasticsearch.help.ProEsHelper;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ProductConstant;
import com.xbongbong.saas.enums.ShowTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.business.InventoryEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.QuotationEnum;
import com.xbongbong.saas.enums.business.RefundEnum;
import com.xbongbong.saas.enums.business.TransferEnum;
import com.xbongbong.saas.enums.business.WorkReportFieldEnum;
import com.xbongbong.saas.help.AnalyticalHelp;
import com.xbongbong.saas.help.SaveFormatHelp;
import com.xbongbong.saas.model.PaasFormRichTextModel;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.help.ProPermissionHelp;
import com.xbongbong.util.ImportDataUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 *
 * @author 魏荣杰
 * @date 2020/12/30 10:22
 * @since
 * @version
 */
@Component
public abstract class AbstractFormDataUpdateService extends AbstractParentUpdateFormDataService<PaasFormEntityExt, PaasFormDataEntity> implements FormDataUpdateService<PaasFormEntityExt, PaasFormDataEntity> {

    private static final Logger LOG = LoggerFactory.getLogger(AbstractFormDataUpdateService.class);

    @Resource
    private FormDataHelp formDataHelp;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private FormDataValidateDataHelp formDataValidateDataHelp;
    @Resource
    private ProEsHelper proEsHelper;
    @Resource
    private PaasFormRichTextModel paasFormRichTextModel;
    @Resource
    protected CommonHelp commonHelp;
    @Resource
    private AnalyticalHelp analyticalHelp;
    @Resource
    private OperationLogFactory operationLogFactory;
    @Resource
    private CommonPermissionHelp commonPermissionHelp;
//    @Resource
//    private RichTextService richTextService;
//
//    /**
//     * 更新表单富文本
//     *
//     * @param formDataUpdateDTO
//     * @param richTextData
//     * @return
//     */
//    protected Integer updateFormRichText(FormDataUpdateDTO formDataUpdateDTO, Object richTextData) {
//        return richTextService.updateFormRichText(formDataUpdateDTO, richTextData);
//    }
//
//    /**
//     * 移除富文本
//     *
//     * @param data Json数据
//     * @return 富文本数据
//     */
//    protected Object removeRichText(JSONObject data){
//        return FormDataUtil.removeRichText(data);
//    }
//
//    /**
//     * 备份富文本
//     *
//     * @param workflowBackupDataEntity
//     * @param businessType
//     * @param saasMark
//     */
//    protected void backupRichText(WorkflowBackupDataEntity workflowBackupDataEntity, Integer businessType, Integer saasMark){
//        richTextService.backupRichText(workflowBackupDataEntity, businessType, saasMark);
//    }

    /**
     * 更新后保存日志
     * @param formDataUpdateDTO
     * @param newPaasFormDataEntity
     * @param updateVO
     * @param beforeUpdateVO
     * @return void
     * @author 吴峰
     * @date 2021/2/23 16:03
     * @throws XbbException
     */
    @Override
    public void afterSaveLog(FormDataUpdateDTO formDataUpdateDTO, PaasFormEntityExt paasFormEntityExt, PaasFormDataEntity newPaasFormDataEntity, PaasFormDataEntity oldPaasFormDataEntity, UpdateVO updateVO, BeforeUpdateVO beforeUpdateVO) throws XbbException {
        OperationLogHandle operationLogHandle = operationLogFactory.getOperationLogHandle(formDataUpdateDTO.getSaasMark(),formDataUpdateDTO.getBusinessType());
        UpdateOperationLogDTO UpdateOperationLogDTO = new UpdateOperationLogDTO(formDataUpdateDTO,newPaasFormDataEntity,updateVO,beforeUpdateVO);
        operationLogHandle.update(UpdateOperationLogDTO);
    }

    @Override
    public BeforeUpdateVO beforeSave(FormDataUpdateDTO formDataUpdateDTO) throws XbbException {
        try {
            Long dataId = formDataUpdateDTO.getDataId();
            String corpid = formDataUpdateDTO.getCorpid();
            Long formId = formDataUpdateDTO.getFormId();
            Integer saasMark = formDataUpdateDTO.getSaasMark();
            Integer businessType = formDataUpdateDTO.getBusinessType();
            JSONObject newData = formDataUpdateDTO.getDataList();
            boolean isImport = Objects.equals(formDataUpdateDTO.getIsImport(), 1);
            if ( !isImport ) {
                // 编辑权限校验
                VerifyUpdatePermissionDTO verifyUpdatePermissionDTO = new VerifyUpdatePermissionDTO();
                BeanUtil.copyProperties(formDataUpdateDTO, verifyUpdatePermissionDTO);
                ProPermissionHelp.verifyEditPermission(verifyUpdatePermissionDTO);
            }
            // 发票、回款单金额明细处理
            JSONArray amountDetail = FastJsonHelper.getAmountDetail(newData);
            formDataUpdateDTO.setAmountDetail(amountDetail);

            PaasFormDataEntity oldPaasFormDataEntity = formDataHelp.getFormDataEntity(formDataUpdateDTO.getCorpid(), formDataUpdateDTO.getSaasMark(), businessType, formDataUpdateDTO.getDataId());
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(oldPaasFormDataEntity.getFormId(), oldPaasFormDataEntity.getCorpid());
            List<FieldAttrEntity> fieldList = JSON.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            Map<String, FieldAttrEntity> explainMap = new HashMap<>(fieldList.size());
            fieldList.forEach(item->explainMap.put(item.getAttr(), item));
            PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
            //保证数据正确
            formDataUpdateDTO.setAppId(paasFormExplainEntity.getAppId());
            formDataUpdateDTO.setMenuId(paasFormExplainEntity.getMenuId());
            formDataUpdateDTO.setFormId(paasFormExplainEntity.getFormId());
            BeanUtil.copyProperties(formDataUpdateDTO, paasFormDataEntity);
            if ( Objects.nonNull(formDataUpdateDTO.getOwnerId()) && !formDataUpdateDTO.getOwnerId().isEmpty() ) {
                paasFormDataEntity.setOwnerId(Objects.toString(formDataUpdateDTO.getOwnerId().get(0).getId(), ""));
            }
            paasFormDataEntity.setId(formDataUpdateDTO.getDataId());

            paasFormDataEntity.setDepartmentId(formDataUpdateDTO.getDepartmentId());
            PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(formDataUpdateDTO.getFormId(), formDataUpdateDTO.getCorpid());
            if ( paasFormEntityExt == null ) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
            }
            // 设置工作报告补发状态
            if (Objects.equals(XbbRefTypeEnum.WORK_REPORT.getCode(), businessType)) {
                JSONObject oldData = oldPaasFormDataEntity.getData();
                Integer isReissue = oldData.getInteger(WorkReportFieldEnum.IS_RESSUE.getAttr());
                isReissue = Objects.isNull(isReissue) ? BasicConstant.ZERO : isReissue;
                newData.put(WorkReportFieldEnum.IS_RESSUE.getAttr(), isReissue);
            }
            ValidateDataDTO validateDataDTO = new ValidateDataDTO();
            BeanUtil.copyProperties(formDataUpdateDTO, validateDataDTO);
            List<String> attrList = formDataUpdateDTO.getAttrList();
            if (Objects.equals(formDataUpdateDTO.getIsImport(), BasicConstant.ONE) && CollectionsUtil.isNotEmpty(attrList)) {
                // 部分字段导入的时候，validateDataDTO的explainMap传的是剔除了无需导入的字段map，跳过无需导入字段的通用校验
                // saasSaveHelp.beforeSave(validateDataDTO);方法后面又把全部字段的explainMap赋值给validateDataDTO，防止后面要用其它字段解释
                Map<String, FieldAttrEntity> simpleExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                for (String s : attrList) {
                    FieldAttrEntity fieldAttrEntity = explainMap.get(s);
                    if (Objects.nonNull(fieldAttrEntity)) {
                        simpleExplainMap.put(s, fieldAttrEntity);
                    }
                }
                validateDataDTO.setExplainMap(simpleExplainMap);
            } else {
                validateDataDTO.setExplainMap(explainMap);
            }

            validateDataDTO.setData(newData);
            validateDataDTO.setExplainMap(explainMap);
            validateDataDTO.setDataId(formDataUpdateDTO.getDataId());
            validateDataDTO.setOwnerIds(formDataUpdateDTO.getOwnerId());
            if(Objects.nonNull(formDataUpdateDTO.getIsCover())){
                validateDataDTO.setIsCover(formDataUpdateDTO.getIsCover());
            }
            ProSaveHelp.analyticalData(validateDataDTO);
            formDataUpdateDTO.setCoUserId(validateDataDTO.getCoUserId());
            setSpecialParam(formDataUpdateDTO);
            formDataValidateDataHelp.validateData(validateDataDTO);
            // TODO: 2021/3/3  
            if (isImport) {
                // 覆盖导入时，针对标识字段不覆盖，其他字段可覆盖
                JSONObject oldData = oldPaasFormDataEntity.getData();
                //报价单组号不可更改
                if (Objects.equals(businessType, XbbRefTypeEnum.QUOTATION.getCode())) {
                    Object isNew = oldData.get(QuotationEnum.IS_NEW.getAttr());
                    if (Objects.equals(isNew, BasicConstant.ZERO)) {
                        throw new XbbException(QuotationErrorCodeEnum.API_ERROR_246008);
                    }
                    String oldGroupNumber = Objects.toString(oldData.get(QuotationEnum.GROUP_NUMBER.getAttr()), "");
                    String newGroupNumber = Objects.toString(newData.get(QuotationEnum.GROUP_NUMBER.getAttr()), "");
                    if (!Objects.equals(oldGroupNumber, newGroupNumber)) {
                        throw new XbbException(QuotationErrorCodeEnum.API_ERROR_246005);
                    }
                }
                //覆盖导入中开放关联数据字段覆盖导入
                List<Integer> unnecessaryFieldType = FieldTypeEnum.getUnnecessaryFieldType();
                explainMap.forEach((key, value) -> {
                    //判断退货退款导入无需覆盖字段
                    boolean isRefundFinalAttr = Objects.equals(value.getAttr(), RefundEnum.REFUND_AMOUNT.getAttr()) || Objects.equals(value.getAttr(), RefundEnum.PAYMENT_SHEETS.getAttr())
                            || Objects.equals(value.getAttr(), RefundEnum.INVOICES.getAttr()) || Objects.equals(value.getAttr(), RefundEnum.PAYMENTS.getAttr());
                    if (Objects.equals(businessType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())
                            && (Objects.equals(value.getAttr(), CustomerManagementEnum.IS_ARCHIVED.getAttr()))) {
                    } else if (Objects.equals(businessType, XbbRefTypeEnum.CLUE.getCode())
                            && (Objects.equals(value.getAttr(), ClueEnum.IS_ARCHIVED.getAttr()))) {
                    } else if (Objects.equals(businessType, XbbRefTypeEnum.REFUND.getCode()) && isRefundFinalAttr) {
                        newData.put(key, oldData.get(key));
                    } else if (Objects.equals(businessType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode()) && Objects.equals(value.getAttr(), CustomerManagementEnum.CREATOR.getAttr())) {
                        newData.put(key, oldData.get(key));
                    }else if (Objects.equals(businessType, XbbRefTypeEnum.PRODUCT.getCode()) && Objects.equals(value.getAttr(), ProductEnum.ENABLE_MULTI_UNIT.getAttr())){
                    } else if (((Objects.equals(value.getIsRedundant(), 0)
                            && (!ShowTypeEnum.getAddShowType().contains(value.getShowType()))
                            || StringUtil.isNotEmpty(value.getUnableEditMemo())) ||
                            unnecessaryFieldType.contains(value.getFieldType()))) {
                        newData.put(key, oldData.get(key));
                    } else if (Objects.equals(businessType, XbbRefTypeEnum.TRANSFER.getCode()) && Objects.equals(value.getAttr(), TransferEnum.TRANSFER_TYPE.getAttr())){
                        newData.put(key, oldData.get(key));
                    } else if (Objects.equals(businessType, XbbRefTypeEnum.INVENTORY.getCode()) && Objects.equals(value.getAttr(), InventoryEnum.INVENTORY_TYPE.getAttr())){
                        newData.put(key, oldData.get(key));
                    }
                    if (Objects.isNull(newData.get(key))) {
                        newData.put(key, null);
                    }
                });
                if (Objects.equals(formDataUpdateDTO.getIsCover(), 1) && CollectionsUtil.isNotEmpty(attrList)) {
                    // oldData的旧值赋给newData里
                    ImportDataUtil.setOldData(newData, oldData, attrList);
                    ImportDataUtil.setOldDepartmentId(oldPaasFormDataEntity.getDepartmentId(), validateDataDTO.getDepartmentId(), explainMap, attrList);

                }
                validateDataDTO.setData(newData);
            }
            validateDataDTO.setCreatorId(oldPaasFormDataEntity.getCreatorId());
            validateDataDTO.setOldOwnerId(oldPaasFormDataEntity.getOwnerId());
            validateDataDTO.setPaasFormDataEntity(oldPaasFormDataEntity);
            //isNew标识代表是不是新增 true代表新增 false代表编辑
            validateDataDTO.setIsNew(false);
            // TODO 不懂为啥标签要在saasSaveHelp.beforeSave里解析，为什么不放在ProSaveHelp.analyticalData
            SaveFormatHelp.dealLabelData(validateDataDTO.getData(), explainMap);
            analyticalHelp.beforeSave(validateDataDTO);
//            saasSaveHelp.beforeSave(validateDataDTO);
            // 重新赋值
            validateDataDTO.setExplainMap(explainMap);
            // 产品可见人和可见部门
            if (XbbRefTypeEnum.hasVisibleRangeBusiness().contains(validateDataDTO.getBusinessType()) || Objects.equals(validateDataDTO.getBusinessType(), XbbRefTypeEnum.COMPETITOR.getCode())) {
                formDataUpdateDTO.setVisbleDept(validateDataDTO.getVisbleDept());
                formDataUpdateDTO.setVisbleUser(validateDataDTO.getVisbleUser());
            }
            if ( CollectionsUtil.isNotEmpty(amountDetail) ) {
                SaasNeedRedundantAttrPojo saasNeedRedundantAttrPoJo = validateDataDTO.getSaasNeedRedundantAttrPoJo();
                saasNeedRedundantAttrPoJo.setAmountDetail(amountDetail);
            }
            // 不要删除这行，如果需要删除这行，需要在各个业务对saasNeedRedundantAttrPoJo单独赋值
            formDataUpdateDTO.setSaasNeedRedundantAttrPoJo(validateDataDTO.getSaasNeedRedundantAttrPoJo());
            // 所属部门的id，由前端传入
            paasFormDataEntity.setDepartmentId(validateDataDTO.getDepartmentId());
            paasFormDataEntity.setCreatorId(validateDataDTO.getCreatorId());
            formDataUpdateDTO.setDepartmentId(validateDataDTO.getDepartmentId());

            formDataUpdateDTO.getDataList().remove(FieldTypeEnum.CREATORID.getAlias());
            paasFormDataEntity.setData(formDataUpdateDTO.getDataList());
            paasFormDataEntity.setMenuId(paasFormEntityExt.getMenuId());

            formDataUpdateDTO.setExplainMap(explainMap);
            // 覆盖导入 开启严控模式 ,流水号不更新
            FieldAttrEntity serialNoEntity = explainMap.get(FieldTypeEnum.SERIALNO.getAlias());
            if (Objects.nonNull(serialNoEntity) && Objects.equals(serialNoEntity.getStrictController(), BasicConstant.ONE) && Objects.equals(formDataUpdateDTO.getIsImport(), 1)){
                paasFormDataEntity.setSerialNo(oldPaasFormDataEntity.getSerialNo());
            }

            //导入不触发
            //是否启用新工作流
            if (isEnableNewWorkflow(formDataUpdateDTO, explainMap, paasFormDataEntity, oldPaasFormDataEntity)) {
                if (!formDataUpdateDTO.getIsSatisfyTrigger()) {
                    // 无需走工作流
                    paasFormDataEntity.setFlowStatus(null);
                }
                BeforeUpdateVO beforeUpdateVO = new BeforeUpdateVO(paasFormEntityExt, explainMap, paasFormDataEntity, oldPaasFormDataEntity, fieldList, validateDataDTO.getSaasNeedRedundantAttrPoJo(), 1);
                Long backUpDataId = backupData(formDataUpdateDTO, beforeUpdateVO, paasFormEntityExt, paasFormDataEntity, oldPaasFormDataEntity);
                beforeUpdateVO.setBackupDataId(backUpDataId);
                return beforeUpdateVO;
            }

            // 进入审批
            //需要拼装富文本字段判断是否需要更新进审批
            addRichTextByDataId(dataId, corpid, formId, businessType, saasMark, DelEnum.NORMAL.getDel(), oldPaasFormDataEntity.getData());
            Integer noApprovalRequired = startProcess(formDataUpdateDTO, paasFormDataEntity, oldPaasFormDataEntity, paasFormEntityExt, formDataUpdateDTO.getSaasNeedRedundantAttrPoJo());
            paasFormDataEntity.getData().remove(FieldTypeEnum.OWNERID.getAlias());
            paasFormDataEntity.getData().remove(FieldTypeEnum.COUSERID.getAlias());
            paasFormDataEntity.getData().remove(FieldTypeEnum.SERIALNO.getAlias());
            paasFormDataEntity.getData().remove(FieldTypeEnum.UPDATETIME.getAlias());
            paasFormDataEntity.getData().remove(FieldTypeEnum.ADDTIME.getAlias());
            return new BeforeUpdateVO(paasFormEntityExt, explainMap, paasFormDataEntity, oldPaasFormDataEntity, fieldList, validateDataDTO.getSaasNeedRedundantAttrPoJo(), noApprovalRequired);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("abstractFormDataUpdate.beforeSave 出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }


    private void addRichTextByDataId(Long dataId, String corpid, Long formId, Integer businessType, Integer saasMark, Integer del, JSONObject data) {
        PaasFormRichTextEntity paasFormRichTextEntity = new PaasFormRichTextEntity(dataId, corpid, formId, businessType, saasMark, del);
        PaasFormRichTextEntity entity = paasFormRichTextModel.getByDataId(paasFormRichTextEntity);
        if (Objects.nonNull(entity)) {
            data.put(RichTextEnum.RICH_TEXT.getAttr(), entity.getData());
        }
    }

    public void setSpecialParam(FormDataUpdateDTO formDataUpdateDTO) {
        if (Objects.equals(formDataUpdateDTO.getBusinessType(), XbbRefTypeEnum.PRODUCT.getCode())) {
            JSONObject data = formDataUpdateDTO.getDataList();
            JSONObject specObj = data.getJSONObject(ProductEnum.SPECIFICATION.getAttr());
            // 前端的级联控件兼容
            if (Objects.isNull(specObj) || (Objects.equals(specObj.getInteger(ProductConstant.ADVANCED_MODE), 0))) {
                if (Objects.equals(data.getInteger(ProductEnum.IS_NOTIFY.getAttr()), 1)) {
                    List<StockNotifyPojo> stockNotifyList = data.getJSONArray(ProductEnum.STOCK_NOTIFY.getAttr()).toJavaList(StockNotifyPojo.class);
                    if (StringUtil.isEmpty(specObj.getString(ProductConstant.SINGLE_SPEC))) {
                        for (StockNotifyPojo stockNotifyPojo : stockNotifyList) {
                            // 没有规格值得时候用空字符串
                            if (Objects.isNull(stockNotifyPojo.getArray_1())) {
                                JSONArray jsonArray = new JSONArray();
                                JSONObject jsonObject = new JSONObject();
                                jsonObject.put("", "");
                                jsonArray.add(jsonObject);
                                stockNotifyPojo.setArray_1(jsonArray);
                            }
                        }
                    } else {
                        for (StockNotifyPojo stockNotifyPojo : stockNotifyList) {
                            // 有规格值得时候空字符串报错
                            if (Objects.nonNull(stockNotifyPojo.getArray_1())) {
                                stockNotifyPojo.getArray_1().removeIf(obj -> JSON.parseObject(obj.toString()).containsKey(""));
                            }
                        }
                    }
                    data.put(ProductEnum.STOCK_NOTIFY.getAttr(), JSON.parseArray(JSON.toJSONString(stockNotifyList)));
                }
            }
        }
    }
    /**
     * 设置部分属性，用于返回
     * @param subFormData 子表单数据封装
     * @param data 主表数据
     * @param updateTime 更新时间
     * @param addTime 创建时间
     * @param departmentId 所属部门
     * @param serialNo 流水号
     * @param ownerId 负责人
     * @param paasFormDataEntity 数据实体
     * @param beforeUpdateVO
     * @return void
     * @author 吴峰
     * @date 2021/2/3 15:14
     * @throws XbbException
     */
    protected void setPartialAttributes(JSONObject subFormData, JSONObject data, Long updateTime, Long addTime, String serialNo, Long departmentId, String ownerId, PaasFormDataEntity paasFormDataEntity, BeforeUpdateVO beforeUpdateVO) {
        paasFormDataEntity.setSubFormData(subFormData);
        paasFormDataEntity.setData(data);
        paasFormDataEntity.setUpdateTime(updateTime);
        paasFormDataEntity.setAddTime(addTime);
        paasFormDataEntity.setSerialNo(serialNo);
        paasFormDataEntity.setDepartmentId(departmentId);
        paasFormDataEntity.setOwnerId(ownerId);
        beforeUpdateVO.setPaasFormDataEntity(paasFormDataEntity);
    }


    public void afterSaveRollBack( FormDataUpdateDTO formDataUpdateDTO, UpdateVO updateVO, BeforeUpdateVO beforeUpdateVO,  ReRollBackEntity reRollBackEntity) throws XbbException {
        try {
            PaasFormDataEntity newPaasFormDataEntity = null;
            if (Objects.nonNull(updateVO)) {
                newPaasFormDataEntity = updateVO.getPaasFormDataEntity();
            }
            PaasFormDataEntity oldPaasFormDataEntity = beforeUpdateVO.getOldPaasFormData();
            Long dataId = formDataUpdateDTO.getDataId();
            String corpid = formDataUpdateDTO.getCorpid();
            Integer saasMark = formDataUpdateDTO.getSaasMark();
            Integer businessType = formDataUpdateDTO.getBusinessType();
            oldPaasFormDataEntity.getData().remove(FieldTypeEnum.UPDATETIME.getAlias());
            oldPaasFormDataEntity.getData().remove(FieldTypeEnum.CREATORID.getAlias());
            oldPaasFormDataEntity.getData().remove(FieldTypeEnum.ADDTIME.getAlias());
            oldPaasFormDataEntity.getData().remove(FieldTypeEnum.OWNERID.getAlias());
            oldPaasFormDataEntity.getData().remove(FieldTypeEnum.SERIALNO.getAlias());
            proEsHelper.reductionEsInUpdate(oldPaasFormDataEntity,oldPaasFormDataEntity.getId(),oldPaasFormDataEntity.getCorpid(), businessType,saasMark);

            // TODO
//            AbstractFormDataUpdateRollBackService rollBackService = FormDataUpdateRollBackFactory.getRollBackService(businessType, saasMark);
//            if (Objects.nonNull(rollBackService)) {
//                rollBackService.rollBack4Update(newPaasFormDataEntity, oldPaasFormDataEntity, dataId, corpid, saasMark, businessType, reRollBackEntity);
//            }
        } catch (Exception e) {
            LOG.error("abstractFormDataUpdateServiceImpl.afterSaveRollBack回滚失败：", e);
        }
    }


    @Override
    public void validatePermission(FormDataUpdateDTO formDataUpdateDTO) throws XbbException {
        boolean isImport = Objects.equals(formDataUpdateDTO.getIsImport(), 1);
        if ( isImport ) {
            return;
        }
        // 编辑权限校验
        VerifyUpdatePermissionDTO verifyUpdatePermissionDTO = new VerifyUpdatePermissionDTO();
        BeanUtil.copyProperties(formDataUpdateDTO, verifyUpdatePermissionDTO);
        ProPermissionHelp.verifyEditPermission(verifyUpdatePermissionDTO);
    }

    @Override
    public PaasFormEntityExt getForm(FormDataUpdateDTO formDataUpdateDTO) throws XbbException {
        PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(formDataUpdateDTO.getFormId(), formDataUpdateDTO.getCorpid());
        if ( paasFormEntityExt == null ) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        paasFormModel.validateByPermission(paasFormEntityExt, formDataUpdateDTO.getLoginUser());
        return paasFormEntityExt;
    }

    @Override
    public PaasFormDataEntity getFormData(FormDataUpdateDTO formDataUpdateDTO, Map<String, FieldAttrEntity> explainMap) throws XbbException {
        String corpid = formDataUpdateDTO.getCorpid();
        Long dataId = formDataUpdateDTO.getDataId();
        Integer saasMark = formDataUpdateDTO.getSaasMark();
        Integer businessType = formDataUpdateDTO.getBusinessType();
        PaasFormDataEntity paasFormDataEntity = formDataHelp.getFormDataWithTeam(corpid, saasMark, businessType, dataId);
        //现在除了需要判断当前人有没有这个业务编辑的表单权限，还需要判断有没有这条数据的编辑权限，外联那边通过按钮控制不住，所以这边统一做校验
        handleEditDataPermission(formDataUpdateDTO,explainMap, paasFormDataEntity);
        return paasFormDataEntity;
    }

    @Override
    public List<FieldAttrEntity> getExplainList(FormDataUpdateDTO formDataUpdateDTO, String corpid, Long formId, Integer saasMark, Integer businessType) throws XbbException {
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
        //保证数据正确
        formDataUpdateDTO.setAppId(paasFormExplainEntity.getAppId());
        formDataUpdateDTO.setMenuId(paasFormExplainEntity.getMenuId());
        formDataUpdateDTO.setFormId(paasFormExplainEntity.getFormId());
        return JSON.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
    }


    @Override
    public void importSetData(ValidateDataDTO validateDataDTO, Map<String, FieldAttrEntity> explainMap, PaasFormDataEntity oldDataEntity, JSONObject newData, List<String> attrList) throws XbbException {
        JSONObject oldData = oldDataEntity.getData();
        List<String> stageRelateFields = Arrays.asList(PaasStageEnum.STAGE_PROCESS_ID.getAttr(), PaasStageEnum.STAGE_ID.getAttr(), PaasStageEnum.STAGE_RATIO.getAttr());
        explainMap.forEach((key, value) -> {

            //判断无需覆盖字段
            boolean notImport = ((Objects.equals(value.getIsRedundant(), 0)
                    && (!ShowTypeEnum.getAddShowType().contains(value.getShowType()))
                    || StringUtil.isNotEmpty(value.getUnableEditMemo()))
                    || FieldTypeEnum.getUnnecessaryFieldType().contains(value.getFieldType()))
                    || stageRelateFields.contains(key)
                    || Objects.equals(FieldTypeEnum.TEMPLATE_FIELD.getType(),value.getFieldType());

            if (!notImport) {
                // 业务层自己实现无需覆盖字段逻辑
                businessImportSetData(value, oldData, newData);
            } else {
                newData.put(key, oldData.get(key));
            }

            if (Objects.isNull(newData.get(key))) {
                newData.put(key, null);
            }
        });
        if (CollectionsUtil.isNotEmpty(attrList)) {
            // oldData的旧值赋给newData里
            ImportDataUtil.setOldData(newData, oldData, attrList);
            ImportDataUtil.setOldDepartmentId(oldDataEntity.getDepartmentId(), validateDataDTO.getDepartmentId(), explainMap, attrList);
        }
    }

    @Override
    public UpdateValidateReturnPojo analyticalData(FormDataUpdateDTO formDataUpdateDTO, ValidateDataDTO validateDataDTO, PaasFormDataEntity oldPaasFormDataEntity, Map<String, FieldAttrEntity> explainMap) throws XbbException {
        ProSaveHelp.analyticalData(validateDataDTO);
        formDataValidateDataHelp.validateData(validateDataDTO);
        validateDataDTO.setCreatorId(oldPaasFormDataEntity.getCreatorId());
        validateDataDTO.setOldOwnerId(oldPaasFormDataEntity.getOwnerId());
        validateDataDTO.setPaasFormDataEntity(oldPaasFormDataEntity);
        //isNew标识代表是不是新增 true代表新增 false代表编辑
        validateDataDTO.setIsNew(false);
        analyticalHelp.beforeSave(validateDataDTO);
        // 存放所属部门
        formDataUpdateDTO.setDepartmentId(validateDataDTO.getDepartmentId());
        return new UpdateValidateReturnPojo();
    }

    @Override
    public void importAnalyticalData(ValidateDataDTO validateDataDTO, PaasFormDataEntity oldPaasFormDataEntity, Map<String, FieldAttrEntity> explainMap, FormDataUpdateDTO formDataUpdateDTO) throws XbbException {
        ProSaveHelp.analyticalData(validateDataDTO);
        formDataValidateDataHelp.validateData(validateDataDTO);
        // 先放回原值
        importSetData(validateDataDTO, explainMap, oldPaasFormDataEntity, validateDataDTO.getData(), formDataUpdateDTO.getAttrList());

        validateDataDTO.setCreatorId(oldPaasFormDataEntity.getCreatorId());
        validateDataDTO.setOldOwnerId(oldPaasFormDataEntity.getOwnerId());
        validateDataDTO.setPaasFormDataEntity(oldPaasFormDataEntity);
        //isNew标识代表是不是新增 true代表新增 false代表编辑
        validateDataDTO.setIsNew(false);
        analyticalHelp.beforeSave(validateDataDTO);
    }

    @Override
    public PaasFormDataEntity getData(FormDataUpdateDTO formDataUpdateDTO, PaasFormDataEntity oldPaasFormDataEntity, JSONObject data, Long departmentId) throws XbbException {
        PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
        paasFormDataEntity.setCorpid(formDataUpdateDTO.getCorpid());
        if ( Objects.nonNull(formDataUpdateDTO.getOwnerId()) && !formDataUpdateDTO.getOwnerId().isEmpty() ) {
            paasFormDataEntity.setOwnerId(Objects.toString(formDataUpdateDTO.getOwnerId().get(0).getId(), ""));
        }
        paasFormDataEntity.setId(formDataUpdateDTO.getDataId());
        paasFormDataEntity.setAppId(formDataUpdateDTO.getAppId());
        paasFormDataEntity.setMenuId(formDataUpdateDTO.getMenuId());
        paasFormDataEntity.setFormId(formDataUpdateDTO.getFormId());
        paasFormDataEntity.setDepartmentId(departmentId);
        paasFormDataEntity.setSerialNo(formDataUpdateDTO.getSerialNo());
        paasFormDataEntity.setData(data);
        paasFormDataEntity.setCreatorId(oldPaasFormDataEntity.getCreatorId());
        return paasFormDataEntity;
    }

    @Override
    public PaasFormDataEntity getImportData(FormDataUpdateDTO formDataUpdateDTO, Map<String, FieldAttrEntity> explainMap, PaasFormDataEntity oldPaasFormDataEntity, JSONObject data, Long departmentId) throws XbbException {
        PaasFormDataEntity paasFormDataEntity = getData(formDataUpdateDTO, oldPaasFormDataEntity, data, departmentId);
        // 覆盖导入 开启严控模式 ,流水号不更新
        FieldAttrEntity serialNoEntity = explainMap.get(FieldTypeEnum.SERIALNO.getAlias());
        if (Objects.nonNull(serialNoEntity) && Objects.equals(serialNoEntity.getStrictController(), BasicConstant.ONE)){
            paasFormDataEntity.setSerialNo(oldPaasFormDataEntity.getSerialNo());
        }
        return paasFormDataEntity;
    }

    @Override
    public BeforeUpdateVO startWorkFlowOrProcess(PaasFormDataEntity paasFormDataEntity, PaasFormDataEntity oldPaasFormDataEntity, PaasFormEntityExt paasFormEntityExt, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo, FormDataUpdateDTO formDataUpdateDTO, Map<String, FieldAttrEntity> explainMap, List<FieldAttrEntity> explainList) throws XbbException {
        //导入不触发
        //是否启用新工作流
        if (isEnableNewWorkflow(formDataUpdateDTO, explainMap, paasFormDataEntity, oldPaasFormDataEntity)) {
            if (!formDataUpdateDTO.getIsSatisfyTrigger()) {
                // 无需走工作流
                paasFormDataEntity.setFlowStatus(null);
            }
            BeforeUpdateVO beforeUpdateVO = new BeforeUpdateVO(paasFormEntityExt, explainMap, paasFormDataEntity, oldPaasFormDataEntity, explainList, saasNeedRedundantAttrPojo, 1);
            Long backUpDataId = backupData(formDataUpdateDTO, beforeUpdateVO, paasFormEntityExt, paasFormDataEntity, oldPaasFormDataEntity);
            beforeUpdateVO.setBackupDataId(backUpDataId);
            return beforeUpdateVO;
        }

        // 进入审批
        Integer noApprovalRequired = startProcess(formDataUpdateDTO, paasFormDataEntity, oldPaasFormDataEntity, paasFormEntityExt, saasNeedRedundantAttrPojo);
        paasFormDataEntity.getData().remove(FieldTypeEnum.COUSERID.getAlias());
        paasFormDataEntity.getData().remove(FieldTypeEnum.OWNERID.getAlias());
        paasFormDataEntity.getData().remove(FieldTypeEnum.SERIALNO.getAlias());
        paasFormDataEntity.getData().remove(FieldTypeEnum.UPDATETIME.getAlias());
        paasFormDataEntity.getData().remove(FieldTypeEnum.ADDTIME.getAlias());
        return new BeforeUpdateVO(paasFormEntityExt, explainMap, paasFormDataEntity, oldPaasFormDataEntity, explainList, saasNeedRedundantAttrPojo, noApprovalRequired);
    }

    @Override
    public BeforeUpdateVO startWorkFlow(PaasFormDataEntity paasFormDataEntity, PaasFormDataEntity oldPaasFormDataEntity, PaasFormEntityExt paasFormEntityExt, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo, FormDataUpdateDTO formDataUpdateDTO, Map<String, FieldAttrEntity> explainMap, List<FieldAttrEntity> explainList) throws XbbException {
        BeforeUpdateVO beforeUpdateVO = new BeforeUpdateVO(paasFormEntityExt, explainMap, paasFormDataEntity, oldPaasFormDataEntity, explainList, saasNeedRedundantAttrPojo, 1);
        if (isEnableNewWorkflow(formDataUpdateDTO, explainMap, paasFormDataEntity, oldPaasFormDataEntity)) {
            if (!formDataUpdateDTO.getIsSatisfyTrigger()) {
                // 无需走工作流
                paasFormDataEntity.setFlowStatus(null);
            }
            commonPermissionHelp.removeConvertedData(oldPaasFormDataEntity.getData());
            Long backUpDataId = backupData(formDataUpdateDTO, beforeUpdateVO, paasFormEntityExt, paasFormDataEntity, oldPaasFormDataEntity);
            beforeUpdateVO.setBackupDataId(backUpDataId);
        }
        return beforeUpdateVO;
    }

    /**
     * 更新保存后封装入参
     *
     * @param saasFormSaveDTO       保存实体后逻辑入参
     * @param paasFormDataEntity    新实体
     * @param oldPaasFormDataEntity 老实体
     * @author feng.zheng
     * @date 2019/1/30 10:19
     */
    protected void packageSaasFormUpdateSaveDTO(SaasFormSaveDTO saasFormSaveDTO, PaasFormDataEntity paasFormDataEntity, PaasFormDataEntity oldPaasFormDataEntity) {
        paasFormDataEntity.setAddTime(oldPaasFormDataEntity.getAddTime());
        saasFormSaveDTO.setIsNew(false);
        saasFormSaveDTO.setOldPaasFormDataEntity(oldPaasFormDataEntity);
        saasFormSaveDTO.setNewPaasFormDataEntity(paasFormDataEntity);
        saasFormSaveDTO.setNewData(paasFormDataEntity.getData());
        saasFormSaveDTO.setOldData(oldPaasFormDataEntity.getData());
    }

    public void saveFile(FormDataUpdateDTO formDataUpdateDTO, PaasFormDataEntity paasFormDataEntity, UserVO userVO) throws XbbException{
        saveFile(formDataUpdateDTO.getExplainMap(), paasFormDataEntity, formDataUpdateDTO.getBusinessType(), userVO);
    }



    protected void setSystemData(JSONObject data, PaasFormDataEntity paasFormDataEntity) {
        FormDataUtil.setSystemData(data, paasFormDataEntity);
    }

    @Override
    protected Integer getFlowStatus(PaasFormDataEntity formData) {
        Integer flowStatus = formData.getFlowStatus();
        formData.setFlowStatus(null);
        return flowStatus;
    }

    @Override
    protected void updateFlowStatus(Integer flowStatus, String corpid, Long dataId, Integer saasMark, Integer businessType) throws XbbException{
        // 为了保证用户在有修改数据的时候才触发工作流，将flowStatus进行分开更新
        PaasProcessDataEntity paasProcessDataEntity = new PaasProcessDataEntity();
        paasProcessDataEntity.setCorpid(corpid);
        paasProcessDataEntity.setFormDataId(dataId);
        paasProcessDataEntity.setBusinessType(businessType);
        paasProcessDataEntity.setSaasMark(saasMark);
        formDataHelp.updateFormDataStatus(paasProcessDataEntity, flowStatus);
    }
}
